/*
 * Copyright 2011 myTDev.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mytdev.commons.util.messages;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 *
 * @author Yann D'Isanto
 */
public abstract class MessageFormatter {

    public static final Style MESSAGE_ONLY = Style.MESSAGE_ONLY;
    public static final Style TYPE_AND_MESSAGE = Style.TYPE_AND_MESSAGE;

    public abstract String format(Message message);

    public static MessageFormatter getMessageFormatter(String pattern) {
        return new PatternMessageFormatter(pattern);
    }

    public static MessageFormatter getMessageFormatter(Style style) {
        MessageFormatter messageFormatter = null;
        switch (style) {
            case MESSAGE_ONLY:
                messageFormatter = new MessageFormatter() {

                    @Override
                    public String format(Message message) {
                        return message.getMessage();
                    }
                };
                break;
            case TYPE_AND_MESSAGE:
                messageFormatter = new MessageFormatter() {

                    @Override
                    public String format(Message message) {
                        StringBuilder sb = new StringBuilder();
                        return sb.append(message.getType()).append(": ").append(message.getMessage()).toString();
                    }
                };
                break;
        }
        return messageFormatter;
    }

    public enum Style {

        TYPE_AND_MESSAGE,
        MESSAGE_ONLY
    }

    private static class PatternMessageFormatter extends MessageFormatter {

        private static final String MESSAGE_PATTERN = "${message}";
        private static final String TITLE_PATTERN = "${title}";
        private static final String TYPE_PATTERN = "${type}";
        private String pattern;
        private String[] data;
        private Field[] fields;

        public PatternMessageFormatter(String pattern) {
            this.pattern = pattern;
            SortedMap<Integer, Field> indexes = new TreeMap<Integer, Field>();
            int indexOfMessage = pattern.indexOf(MESSAGE_PATTERN);
            int indexOfTitle = pattern.indexOf(TITLE_PATTERN);
            int indexOfType = pattern.indexOf(TYPE_PATTERN);
            if (indexOfMessage > -1) {
                indexes.put(indexOfMessage, Field.MESSAGE);
            }
            if (indexOfTitle > -1) {
                indexes.put(indexOfTitle, Field.TITLE);
            }
            if (indexOfType > -1) {
                indexes.put(indexOfType, Field.TYPE);
            }
            int lastIndex = 0;
            ArrayList<String> list = new ArrayList<String>();
            for (Integer index : indexes.keySet()) {
                list.add(pattern.substring(lastIndex, index));
                switch (indexes.get(index)) {
                    case MESSAGE:
                        lastIndex = index + MESSAGE_PATTERN.length();
                        break;
                    case TITLE:
                        lastIndex = index + TITLE_PATTERN.length();
                        break;
                    case TYPE:
                        lastIndex = index + TYPE_PATTERN.length();
                        break;
                }
            }
            list.add(pattern.substring(lastIndex));
            data = list.toArray(new String[list.size()]);
            fields = indexes.values().toArray(new Field[indexes.size()]);
        }

        @Override
        public String format(Message message) {
            StringBuilder sb = new StringBuilder();
            ArrayList<String> list = new ArrayList<String>(Arrays.asList(data));
            sb.append(list.remove(0));
            for (Field field : fields) {
                switch (field) {
                    case MESSAGE:
                        sb.append(message.getMessage());
                        break;
                    case TITLE:
                        sb.append(message.getTitle());
                        break;
                    case TYPE:
                        sb.append(message.getType());
                        break;
                }
                sb.append(list.remove(0));
            }
            return sb.toString();
        }
    }

    private enum Field {

        MESSAGE,
        TITLE,
        TYPE;
    }
}
